/*
 * Copyright (C) 2012 Rothens
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package rpg;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.io.File;
import javax.swing.JFrame;
import rpg.entities.Player;
import rpg.gfx.Screen;
import rpg.util.BinaryWriter;

/**
 * rothens.tumblr.com
 * @author Rothens
 */
public class RPG extends Canvas implements Runnable{
	

	private boolean running;
	private int FPS = 0;
	private BufferedImage img;
	private Screen screen;
	private int[] pixels;
	private Game game;
	static int WIDTH = 640;
	static int HEIGHT = 480;
	public static final String version = "0.0.8";
	
	public static RPG rpg;
	
	public static KeyboardListener listener = new KeyboardListener();
	
	
	private Thread thread;
	
	public RPG() {
		Dimension size = new Dimension(630, 470); //I dunno why is there a 10px width gap, but this will do it :D
		setSize(size);
		setPreferredSize(size);
		setMinimumSize(size);
		setMaximumSize(size);
		setPreferredSize(size);
		setFocusable(false);
		
		game = new Game();
		
		screen = new Screen(WIDTH, HEIGHT);
		img = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
		pixels = ((DataBufferInt) img.getRaster().getDataBuffer()).getData();
		
	}

	
	public static void main(String[] args) {
		rpg = new RPG();

		
		JFrame frame = new JFrame("Rothens RPG " + version);
		frame.setLayout(new GridLayout());
		
		frame.getContentPane().add(rpg);
		
		frame.pack();
		frame.setResizable(false); //we shouldn't allow resize manually
		frame.setLocationRelativeTo(null); //center the frame on the user's screen
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.addKeyListener(listener);
		frame.setVisible(true);
		
		rpg.start();
		
		
	}
	
	public synchronized void start() {
		if(running){
			return;
		}
		running = true;
		thread = new Thread(this);
		thread.start();
	}
	
	public synchronized void stop() {
		if(!running) {
			return;
		}
		running = false;
		try {
			thread.join();
		} catch (InterruptedException ex) {
			ex.printStackTrace();
		}
	}
	
	public void run(){
		
		double upSec = 0;
		long lastTime = System.nanoTime();
		double secPerTick = 1 / 60.0; //60 FPS
		int cnt = 0;
		int frames = 0;
		
		while(running){
			
			//FPS limit woohoo :D
			long now = System.nanoTime();
			long passed = now - lastTime;
			lastTime = now;
			
			if(passed < 0) {
				passed = 0;
			}
			
			if(passed > 100000000) {
				passed = 100000000;
			}
			
			upSec += passed / 1000000000.0;
			
			boolean ticked = false;
			
			while(upSec > secPerTick) {
				tick();
				upSec -= secPerTick;
				ticked = true;
				cnt++;
				if(cnt % 60 == 0){
					FPS = frames;
					lastTime += 1000;
					frames = 0;
				}
			}
			if(ticked) {
				render();
				frames++;
			}
		}
		
	}

	private void tick(){
		game.tick();
	}
	
	private void render(){
		BufferStrategy bfs = this.getBufferStrategy();
		if(bfs == null) {
			createBufferStrategy(2);
			return;
		}
		screen.render(game);
		System.arraycopy(screen.pixels, 0, pixels, 0, WIDTH * HEIGHT);
		Graphics g = bfs.getDrawGraphics();
		//clear the screen
		g.setColor(Color.black);
		
		g.fillRect(0, 0, 640, 480);
		
		g.drawImage(img, 0, 0, WIDTH, HEIGHT, null);
		g.setColor(Color.red);
		g.drawString(FPS + " FPS", 10, 10);
		g.drawString("tX: " + game.player.getLocation().getTileX() + " tY: " + game.player.getLocation().getTileY(), 10, 20);
		g.dispose();
		bfs.show();
		
		
		
	}
}
